package com.earthea.scaffold.system.service;

import com.earthea.scaffold.common.constant.Constants;
import com.earthea.scaffold.common.enums.CommonStatusEnum;
import com.earthea.scaffold.common.enums.MenuTypeEnum;
import com.earthea.scaffold.domain.Menu;
import com.earthea.scaffold.mapper.MenuMapper;
import com.earthea.scaffold.system.entity.vo.MetaVo;
import com.earthea.scaffold.system.entity.vo.RouterVo;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/**
 * 菜单 业务层处理
 */
@Service
public class MenuService {

    /**
     * Layout组件标识
     */
    private final static String LAYOUT = "Layout";

    /**
     * ParentView组件标识
     */
    private final static String PARENT_VIEW = "ParentView";

    /**
     * InnerLink组件标识
     */
    private final static String INNER_LINK = "InnerLink";

    @Autowired
    private MenuMapper menuMapper;

    public List<Menu> selectMenuTreeByUserId() {
        List<Menu> menus = menuMapper.selectMenuTreeAll();
        return getChildPerms(menus, 0);
    }

    /**
     * 根据父节点的ID获取所有子节点
     *
     * @param list     分类表
     * @param parentId 传入的父节点ID
     * @return String
     */
    private List<Menu> getChildPerms(List<Menu> list, int parentId) {
        List<Menu> returnList = new ArrayList<>();
        for (Menu menu : list) {
            // 根据传入的某个父节点ID,遍历该父节点的所有子节点
            if (menu.getParentId() == parentId) {
                recursionFn(list, menu);
                returnList.add(menu);
            }
        }
        return returnList;
    }

    /**
     * 递归列表
     *
     * @param list     分类表
     * @param children 子节点
     */
    private void recursionFn(List<Menu> list, Menu children) {
        // 得到子节点列表
        List<Menu> childList = getChildList(list, children);
        children.setChildren(childList);
        for (Menu child : childList) {
            if (hasChild(list, child)) {
                recursionFn(list, child);
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<Menu> getChildList(List<Menu> list, Menu children) {
        List<Menu> tlist = new ArrayList<>();
        for (Menu menu : list) {
            if (menu.getParentId().longValue() == children.getMenuId().longValue()) {
                tlist.add(menu);
            }
        }
        return tlist;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<Menu> list, Menu t) {
        return !getChildList(list, t).isEmpty();
    }

    public List<RouterVo> buildMenus(List<Menu> menus) {
        List<RouterVo> routers = new LinkedList<>();
        for (Menu menu : menus) {
            RouterVo router = new RouterVo();
            router.setHidden(CommonStatusEnum.DISABLED.equals(menu.getStatus()));
            router.setName(getRouteName(menu));
            router.setPath(getRouterPath(menu));
            router.setComponent(getComponent(menu));
            router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), menu.getPath()));
            List<Menu> cMenus = menu.getChildren();
            if (CollectionUtils.isNotEmpty(cMenus) && MenuTypeEnum.DIRECTORY.equals(menu.getMenuType())) {
                router.setAlwaysShow(true);
                router.setRedirect("noRedirect");
                router.setChildren(buildMenus(cMenus));
            } else if (isMenuFrame(menu)) {
                router.setMeta(null);
                List<RouterVo> childrenList = new ArrayList<>();
                RouterVo children = new RouterVo();
                children.setPath(menu.getPath());
                children.setComponent(menu.getComponent());
                children.setName(StringUtils.capitalize(menu.getPath()));
                children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), menu.getPath()));
                childrenList.add(children);
                router.setChildren(childrenList);
            } else if (menu.getParentId().intValue() == 0 && isInnerLink(menu)) {
                router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon()));
                router.setPath("/");
                List<RouterVo> childrenList = new ArrayList<>();
                RouterVo children = new RouterVo();
                String routerPath = innerLinkReplaceEach(menu.getPath());
                children.setPath(routerPath);
                children.setComponent(INNER_LINK);
                children.setName(StringUtils.capitalize(routerPath));
                children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), menu.getPath()));
                childrenList.add(children);
                router.setChildren(childrenList);
            }
            routers.add(router);
        }
        return routers;
    }

    /**
     * 获取路由名称
     *
     * @param menu 菜单信息
     * @return 路由名称
     */
    private String getRouteName(Menu menu) {
        // 非外链并且是一级目录（类型为目录）
        if (isMenuFrame(menu)) {
            return StringUtils.EMPTY;
        }
        return StringUtils.capitalize(menu.getPath());
    }

    /**
     * 获取路由地址
     *
     * @param menu 菜单信息
     * @return 路由地址
     */
    private String getRouterPath(Menu menu) {
        String routerPath = menu.getPath();
        // 内链打开外网方式
        if (menu.getParentId().intValue() != 0 && isInnerLink(menu)) {
            routerPath = innerLinkReplaceEach(routerPath);
        }
        // 非外链并且是一级目录（类型为目录）
        if (0 == menu.getParentId().intValue() && MenuTypeEnum.DIRECTORY.equals(menu.getMenuType())) {
            routerPath = "/" + menu.getPath();
        }
        // 非外链并且是一级目录（类型为菜单）
        else if (isMenuFrame(menu)) {
            routerPath = "/";
        }
        return routerPath;
    }

    /**
     * 获取组件信息
     *
     * @param menu 菜单信息
     * @return 组件信息
     */
    private String getComponent(Menu menu) {
        String component = LAYOUT;
        String str2 = menu.getComponent();
        if (StringUtils.isNotEmpty(str2) && !isMenuFrame(menu)) {
            component = menu.getComponent();
        } else {
            String str1 = menu.getComponent();
            if (StringUtils.isEmpty(str1) && menu.getParentId().intValue() != 0 && isInnerLink(menu)) {
                component = INNER_LINK;
            } else {
                String str = menu.getComponent();
                if (StringUtils.isEmpty(str) && isParentView(menu)) {
                    component = PARENT_VIEW;
                }
            }
        }
        return component;
    }

    /**
     * 是否为菜单内部跳转
     *
     * @param menu 菜单信息
     * @return 结果
     */
    private boolean isMenuFrame(Menu menu) {
        return menu.getParentId().intValue() == 0 && MenuTypeEnum.MENU.equals(menu.getMenuType());
    }

    /**
     * 是否为内链组件
     *
     * @param menu 菜单信息
     * @return 结果
     */
    private boolean isInnerLink(Menu menu) {
        return StringUtils.startsWithAny(menu.getPath(), Constants.LINK);
    }

    /**
     * 是否为parent_view组件
     *
     * @param menu 菜单信息
     * @return 结果
     */
    private boolean isParentView(Menu menu) {
        return menu.getParentId().intValue() != 0 && MenuTypeEnum.DIRECTORY.equals(menu.getMenuType());
    }

    /**
     * 内链域名特殊字符替换
     *
     * @return 替换后的内链域名
     */
    private String innerLinkReplaceEach(String path) {
        path = StringUtils.replaceEach(path, new String[]{".", ":"}, new String[]{"/", "/"});
        path = StringUtils.replaceEach(path, Constants.LINK, new String[]{"", "", ""});
        return path;
    }
}
